package com.innovation.ic.im.end.data.schedule;

import com.innovation.ic.im.end.base.model.im_erp9.Account;
import com.innovation.ic.im.end.base.model.im_erp9.AccountRelation;
import com.innovation.ic.im.end.base.model.im_erp9.ChatPair;
import com.innovation.ic.im.end.base.pojo.ServiceResult;
import com.innovation.ic.im.end.base.pojo.constant.RedisStorage;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Configuration
@EnableScheduling
public class importAccountAndChatPairTask extends AbstractSchedule {
    private static final Logger log = LoggerFactory.getLogger(importAccountAndChatPairTask.class);

    /**
     * 先清空account表，再从erp9项目中导入账号的详细信息。再清空chat_pair表，然后向chat_pair表中导入数据
     */
    @Scheduled(cron = "0 30 2 * * ?")
//    @Scheduled(fixedRate = 60000000)
//    @Scheduled(cron = "0 24 14 * * ?")
    private void importAccountAndChatPair() {
        try {
            InterProcessMutex lock = new InterProcessMutex(curatorFramework, zookeeperPathDataParamConfig.getImportAccountAndChatPair());
            if (lock.acquire(zookeeperParamConfig.getWaitingLockTime(), TimeUnit.SECONDS)) {
                log.info("定时任务开启：先清空account表，再从erp9项目中导入账号的详细信息。再清空chat_pair表，然后向chat_pair表中导入数据");
                ServiceResult<List<Account>> accountWithoutDepartmentServiceResult = erp9AdminsService.getAccountWithoutDepartment();
                ServiceResult<List<Account>> accountWithDepartmentServiceResult = erp9AdminsService.getAccountWithDepartment();
                if (null != accountWithoutDepartmentServiceResult && null != accountWithoutDepartmentServiceResult.getResult()
                        && null != accountWithDepartmentServiceResult && null != accountWithDepartmentServiceResult.getResult()) {
                    List<Account> accountWithoutDepartmentList = accountWithoutDepartmentServiceResult.getResult();
                    List<Account> accountWithDepartmentList = accountWithDepartmentServiceResult.getResult();
                    for (int i = 0; i < accountWithoutDepartmentList.size(); i++) {
                        Account accountWithoutDepartment = accountWithoutDepartmentList.get(i);
                        for (int j = 0; j < accountWithDepartmentList.size(); j++) {
                            Account accountWithDepartment = accountWithDepartmentList.get(j);
                            if (accountWithoutDepartment.getId().equals(accountWithDepartment.getId())) {
                                accountWithoutDepartment.setDepartmentName(accountWithDepartment.getDepartmentName());
                            }
                        }
                    }

                    // 清空备份表 temp_account
                    log.info("-----清空备份表 temp_account-----");
                    tempAccountService.truncateTable();
                    log.info("-----清空备份表 temp_account完成-----");

                    // 备份account表中登录状态和最近登录时间不为空的数据
                    log.info("-----备份account表中登录状态和最近登录时间不为空的数据-----");
                    tempAccountService.backupAccount();
                    log.info("-----备份account表中登录状态和最近登录时间不为空的数据完成-----");

                    // 清空account表中erp导入的账号数据
                    accountService.deleteErpAccountData();
                    // 向account表中导入数据
                    accountService.saveAccountList(accountWithoutDepartmentList);

                    // 将备份的TempAccount数据导入回原account表
                    log.info("-----将之前备份的TempAccount数据导入回原account表-----");
                    tempAccountService.insertTempAccountToAccount();
                    log.info("-----将之前备份的TempAccount数据导入回原account表完成-----");

                    // 清空备份表temp_chat_pair数据
                    log.info("清空备份表temp_chat_pair数据");
                    tempChatPairService.truncateTable();

                    // 备份chat_pair表中设置了置顶时间、最近联系时间、内容不可见时间的数据到temp_chat_pair表中
                    log.info("备份chat_pair表中设置了置顶时间、最近联系时间、内容不可见时间和设置了免打扰的数据到temp_chat_pair表中");
                    ServiceResult<Boolean> result = chatPairService.backupLastContactInvisibleIsNotNullData();
                    if (!result.getResult()) {
                        log.warn("备份chat_pair表中设置了置顶时间、最近联系时间、内容不可见时间和设置了免打扰的数据到temp_chat_pair表失败,终止定时任务");
                        throw new Exception("备份chat_pair表中设置了置顶时间、最近联系时间、内容不可见时间和设置了免打扰的数据到temp_chat_pair表失败,终止定时任务");
                    }

                    // 清空chat_pair表，然后向chat_pair表中导入数据
                    chatPairService.truncateTable();

                    int code = 1;
                    List<ChatPair> list = new ArrayList<ChatPair>();
                    // 是否为最后一条数据
                    boolean ifEndData = Boolean.FALSE;

                    log.info("向chat_pair表中导入数据开始");
                    for (int i = 0; i < accountWithoutDepartmentList.size(); i++) {
                        for (int j = i; j < accountWithoutDepartmentList.size(); j++) {
                            // 判断是否为最后一条处理数据
                            if (i == accountWithoutDepartmentList.size() - 1 && j == accountWithoutDepartmentList.size() - 1) {
                                ifEndData = Boolean.TRUE;
                            }

                            if (accountWithoutDepartmentList.get(i).getUsername().equals(accountWithoutDepartmentList.get(j).getUsername())) {
                                // 最后一条数据处理完,但list还有未入库数据的需要入库
                                if (ifEndData && list.size() > 0) {
                                    chatPairService.saveChatPairList(list);
                                    list.clear();
                                }
                                continue;
                            }
                            // 向表chat_pair中插入数据
                            insertChatPairData(accountWithoutDepartmentList.get(i).getUsername(), accountWithoutDepartmentList.get(j).getUsername(), code, ifEndData, list);
                            //SaveChatPairThread saveChatPairThread = new SaveChatPairThread(accountWithoutDepartmentList.get(i).getUsername(), accountWithoutDepartmentList.get(j).getUsername(), code, chatPairService, tempChatPairService);
                            //threadPoolManager.execute(saveChatPairThread);
                            code++;
                        }
                    }

                    // 添加账号关系表中供应商协同账号与销售账号的聊天对数据
                    log.info("添加账号关系表中供应商协同账号与销售账号的聊天对数据开始");
                    code = addAccountRelationChatPairData(code);
                    log.info("添加账号关系表中供应商协同账号与销售账号的聊天对数据结束");

                    // 添加自己和自己的聊天对
                    log.info("添加自己和自己的聊天对开始");
                    for (Account account : accountWithoutDepartmentList) {
                        ChatPair chatPair = new ChatPair();
                        chatPair.setFromUserAccount(account.getUsername());
                        chatPair.setToUserAccount(account.getUsername());
                        chatPair.setCode(code);
                        chatPairService.saveChatPair(chatPair);
                        code++;
                    }
                    log.info("添加自己和自己的聊天对结束");

                    log.info("向chat_pair表中导入数据结束");
                }

                // 将char_pair备份的数据更新到原表中
                log.info("将char_pair备份的数据更新到原表中");
                ServiceResult<Boolean> result = chatPairService.insertTempDataToChatpair();
                if (result.getResult()) {
                    log.info("将char_pair备份的数据更新到原表中成功");
                }

                // 设置系统账号的登录状态为在线
                setSystemAccountLoginOnline();

                // 导入redis中MESSAGE:开头的数据
                importMessageIntoRedis();
                //导入account 数据到Redis中
                importAccountIntoRedis();
                log.info("定时任务结束：importAccountAndChatPair方法执行完成");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加账号关系表中供应商协同账号与销售账号的聊天对数据
     */
    private int addAccountRelationChatPairData(int code) {
        // 查询账号关系表数据
        ServiceResult<List<AccountRelation>> serviceResult = accountRelationService.getAccountRelationListData();
        List<AccountRelation> result = serviceResult.getResult();
        if(result != null && result.size() > 0){
            for(AccountRelation accountRelation : result){
                ChatPair chatPair = new ChatPair();
                chatPair.setFromUserAccount(accountRelation.getScAccountId());
                chatPair.setToUserAccount(accountRelation.getSaleAccountId());
                chatPair.setCode(code);
                chatPairService.saveChatPair(chatPair);

                chatPair = new ChatPair();
                chatPair.setFromUserAccount(accountRelation.getSaleAccountId());
                chatPair.setToUserAccount(accountRelation.getScAccountId());
                chatPair.setCode(code);
                chatPairService.saveChatPair(chatPair);

                code++;
            }
        }

        return code;
    }

    /**
     * 设置系统账号的登录状态为在线
     */
    private void setSystemAccountLoginOnline() {
        // 查询系统账号
        ServiceResult<List<String>> serviceResult = accountService.getSystemAccount();
        List<String> accountList = serviceResult.getResult();
        if(accountList != null && accountList.size() > 0){
            // 设置系统账号登录状态为在线
            accountService.setSystemAccountLoginOnline(accountList);
        }
    }

    /**
     * 导入redis中MESSAGE:开头的数据
     */
    private void importMessageIntoRedis() {
        // 删除redis中MESSAGE:开头的数据
        Boolean deleteResult = redisManager.delRedisDataByKeyPrefix(RedisStorage.MESSAGE_PREFIX);
        if(deleteResult){
            log.info("删除redis中MESSAGE:开头的数据成功");
        }

        // 将message表中的数据导入redis
        log.info("将message表中的数据导入redis");
        ServiceResult<Boolean> serviceResult = messageService.importMessageIntoRedis();
        if (serviceResult.getResult()) {
            log.info("将message表中的数据导入redis完成");
        }
    }

    /**
     * 向表chat_pair中插入数据
     *
     * @param fromUserAccount 发送消息的账号
     * @param toUserAccount   接收消息的账号
     * @param code            聊天对的主键
     */
    private void insertChatPairData(String fromUserAccount, String toUserAccount, Integer code, Boolean ifEndData, List<ChatPair> list) {
        ChatPair chatPairOne = new ChatPair();
        chatPairOne.setFromUserAccount(fromUserAccount);
        chatPairOne.setToUserAccount(toUserAccount);
        chatPairOne.setCode(code);
        list.add(chatPairOne);

        ChatPair chatPairTwo = new ChatPair();
        chatPairTwo.setFromUserAccount(toUserAccount);
        chatPairTwo.setToUserAccount(fromUserAccount);
        chatPairTwo.setCode(code);
        list.add(chatPairTwo);

        // 10000条数据批量插入一次数据库,并且将list清空
        if (list.size() == 10000 || ifEndData) {
            chatPairService.saveChatPairList(list);
            list.clear();
        }
    }

    /**
     * 导入account 数据到Redis中
     */
    public void importAccountIntoRedis() {
        log.info("删除redis中api:v1:account:detailByAdminsId:adminsId:get_ 和 api:v1:account:detailByAccount:account:get_开头的数据" +
                " 和 Redis 中 api:v1:account:findAllOrderByRealNameAsc数据 ,根据Account表的数据,导入redis");
        // 删除redis中api:v1:account:detailByAdminsId:adminsId:get_ 开头的数据
        Boolean deleteResult = redisManager.delRedisDataByKeyPrefix(RedisStorage.ACCOUNT_BY_ADMINS_ID_PREFIX);
        if(deleteResult){
            log.info("删除redis中api:v1:account:detailByAdminsId:adminsId:get_ 开头的数据成功");
        }

        // 删除api:v1:account:detailByAccount:account:get_开头的数据
        Boolean deleteResult1 = redisManager.delRedisDataByKeyPrefix(RedisStorage.ACCOUNT_BY_ACCOUNT_PREFIX);
        if(deleteResult1){
            log.info("删除api:v1:account:detailByAccount:account:get_开头的数据成功");
        }

        //删除redis中api:v1:account:findAllOrderByRealNameAsc数据
        redisManager.del(RedisStorage.ACCOUNT_ALL);
        //根据Account表的数据，导入redis
        log.info("根据Account表的数据，导入redis");
        long l = System.currentTimeMillis();
        ServiceResult<Boolean> booleanServiceResult = accountService.importAccountIntoRedis();
        log.info("根据Account表的数据，导入redis完成,耗时:{}ms", System.currentTimeMillis() - l);
    }
}